package cn.hg.solon.youcan.web.admin.controller.monitor;

import java.util.ArrayList;
import java.util.List;

import org.dromara.hutool.core.array.ArrayUtil;
import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.core.map.MapWrapper;
import org.dromara.hutool.core.text.StrValidator;
import org.dromara.hutool.core.text.escape.EscapeUtil;
import org.dromara.hutool.core.text.split.SplitUtil;
import org.noear.solon.annotation.Controller;
import org.noear.solon.annotation.Inject;
import org.noear.solon.annotation.Mapping;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.handle.MethodType;
import org.noear.solon.core.handle.ModelAndView;
import org.noear.solon.core.handle.Result;
import org.noear.solon.validation.annotation.NotNull;

import com.mybatisflex.core.paginate.Page;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hg.solon.youcan.common.annotation.Log;
import cn.hg.solon.youcan.common.enums.BusinessType;
import cn.hg.solon.youcan.common.web.LayuiPage;
import cn.hg.solon.youcan.framework.web.cache.WebCacheService;
import cn.hg.solon.youcan.web.admin.controller.BaseAdminController;

/**
 * @author 胡高
 */
@Controller
@Mapping("/admin/monitor/cache")
public class CacheController extends BaseAdminController {

    private static final String SERVICE_NAME = "缓存监控";

    private static String VIEW_PATH = "/admin/monitor/cache/";

    @Inject
    private WebCacheService cacheService;

    @Mapping(path = "clearCacheAll", method = MethodType.GET)
    @Log(title = SERVICE_NAME, businessType = BusinessType.CLEAR)
    @SaCheckPermission(value = {"monitor:cache:clear"})
    public Result<?> clearCacheAll(Context ctx) {
        this.cacheService.clearAll();

        return Result.succeed();
    }

    @Mapping(path = "clearCacheKeys", method = MethodType.POST)
    @Log(title = SERVICE_NAME, businessType = BusinessType.DELETE)
    @SaCheckPermission(value = {"monitor:cache:del"})
    public Result<?> clearCacheKeys(Context ctx, @NotNull String cacheName, @NotNull String cacheKeys) {
        if (StrValidator.isBlank(cacheKeys)) {
            return Result.failure();
        }
        List<String> splitKeys = SplitUtil.split(cacheKeys, ",");
        List<String> keys = new ArrayList<>(splitKeys.size());
        splitKeys.stream().forEach(item -> {
            if (StrValidator.isBlank(item)) {
                return;
            }

            keys.add(EscapeUtil.unescape(item));
        });

        this.cacheService.clearCacheKeys(cacheName, ArrayUtil.ofArray(keys, String.class));

        return Result.succeed();
    }

    @Mapping(path = "clearCacheNames", method = MethodType.POST)
    @Log(title = SERVICE_NAME, businessType = BusinessType.DELETE)
    @SaCheckPermission(value = {"monitor:cache:del"})
    public Result<?> clearCacheNames(Context ctx, @NotNull String cacheNames) {
        if (StrValidator.isBlank(cacheNames)) {
            return Result.failure();
        }
        List<String> splitNames = SplitUtil.split(cacheNames, ",");
        List<String> names = new ArrayList<>(splitNames.size());
        splitNames.stream().forEach(item -> {
            if (StrValidator.isBlank(item)) {
                return;
            }

            names.add(EscapeUtil.unescape(item));
        });

        this.cacheService.clearCacheNames(ArrayUtil.ofArray(names, String.class));

        return Result.succeed();
    }

    @Mapping(path = "", method = MethodType.GET)
    @SaCheckLogin
    public ModelAndView index(Context ctx) {
        this.log.info("跳转到[{}]主页面", SERVICE_NAME);

        ModelAndView mav = new ModelAndView(VIEW_PATH + "index.html");

        return mav;
    }

    @Mapping(path = "queryCacheKeys", method = MethodType.POST)
    @SaCheckLogin
    public LayuiPage<MapWrapper<String, String>> queryCacheKeys(Context ctx, @NotNull Integer page,
        @NotNull Integer limit,
        @NotNull String cacheName,
        String word) {
        Page<String> cacheKeyPage = this.cacheService.getCacheKeys(page, limit, cacheName, word);

        List<MapWrapper<String, String>> cacheKeyList = new ArrayList<>();

        cacheKeyPage.getRecords().stream().forEach(item -> {
            MapWrapper<String, String> map = new MapWrapper<>(MapUtil.of("key", item));
            // 做escape转换，用于规避特殊字符
            map.put("escapeKey", EscapeUtil.escape(item));
            cacheKeyList.add(map);
        });

        LayuiPage<MapWrapper<String, String>> layuiPage = new LayuiPage<>(cacheKeyList);
        layuiPage.setCount(cacheKeyPage.getTotalRow());

        return layuiPage;
    }

    @Mapping(path = "queryCacheNames", method = MethodType.POST)
    @SaCheckLogin
    public LayuiPage<MapWrapper<String, String>> queryCacheNames(Context ctx, @NotNull Integer page,
        @NotNull Integer limit, String word) {
        Page<String> cacheNamePage = this.cacheService.getCacheNames(page, limit, word);

        List<MapWrapper<String, String>> cacheNamesList = new ArrayList<>();
        cacheNamePage.getRecords().stream().forEach(item -> {
            MapWrapper<String, String> map = new MapWrapper<>(MapUtil.of("name", item));
            // 做escape转换，用于规避特殊字符
            map.put("escapeName", EscapeUtil.escape(item));
            cacheNamesList.add(map);
        });

        LayuiPage<MapWrapper<String, String>> layuiPage = new LayuiPage<>(cacheNamesList);
        layuiPage.setCount(cacheNamePage.getTotalRow());

        return layuiPage;
    }

    @Mapping(path = "queryCacheValue", method = MethodType.POST)
    @SaCheckLogin
    public Result<?> queryCacheValue(Context ctx, @NotNull String cacheName, @NotNull String cacheKey) {
        Object value = this.cacheService.getCacheValue(cacheName, cacheKey);

        Result<Object> result = Result.succeed();

        result.setData(value);

        return result;
    }

}
